package com.diy.sigmund.diycommon.spring.config.dynamicthreadpool;

import java.util.Objects;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 生成线程池所用的线程，改写了线程池默认的线程工厂，传入线程池名称，便于问题追踪
 *
 * @author ylm-sigmund
 * @since 2023/1/31 9:38
 */
public class MonitorThreadFactory implements ThreadFactory {

    private static final Logger log = LoggerFactory.getLogger(MonitorThreadFactory.class);

    private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);
    private final AtomicInteger uncaughtExceptionCount = new AtomicInteger(0);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    public AtomicInteger getUncaughtExceptionCount() {
        return uncaughtExceptionCount;
    }

    /**
     * 初始化线程工厂
     *
     * @param poolName 线程池名称
     */
    MonitorThreadFactory(String poolName) {
        SecurityManager s = System.getSecurityManager();
        group = Objects.nonNull(s) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
        namePrefix = poolName + "-pool-" + POOL_NUMBER.getAndIncrement() + "-thread-";
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
        if (t.isDaemon()) {
            t.setDaemon(false);
        }
        if (t.getPriority() != Thread.NORM_PRIORITY) {
            t.setPriority(Thread.NORM_PRIORITY);
        }
        t.setUncaughtExceptionHandler((th, throwable) -> {
            this.uncaughtExceptionCount.getAndIncrement();
            log.error("uncaughtException name={},Throwable={}", th.getName(), throwable);
        });
        return t;
    }
}
